#include "MeshCreator.h"
//#include <math.h>
#define PI                                3.14159265359

MeshCreator::MeshCreator()
{
};


MeshCreator::~MeshCreator()
{
};

Mesh MeshCreator::CreateBox(float width, float height, float depth){
	Mesh box = Mesh();

	float w2 = 0.5f*width;
	float h2 = 0.5f*height;
	float d2 = 0.5f*depth;
	
	box.AddVertex({ XMFLOAT3(-w2, h2, -d2), XMFLOAT3(0.0f, 1.0f, 0.0f), XMFLOAT2(1.0f, 0.0f) });
	box.AddVertex({ XMFLOAT3(w2, h2, -d2), XMFLOAT3(0.0f, 1.0f, 0.0f), XMFLOAT2(0.0f, 0.0f) });
	box.AddVertex({ XMFLOAT3(w2, h2, d2), XMFLOAT3(0.0f, 1.0f, 0.0f), XMFLOAT2(0.0f, 1.0f) });
	box.AddVertex({ XMFLOAT3(-w2, h2, d2), XMFLOAT3(0.0f, 1.0f, 0.0f), XMFLOAT2(1.0f, 1.0f) });

	box.AddVertex({ XMFLOAT3(-w2, -h2, -d2), XMFLOAT3(0.0f, -1.0f, 0.0f), XMFLOAT2(0.0f, 0.0f) });
	box.AddVertex({ XMFLOAT3(w2, -h2, -d2), XMFLOAT3(0.0f, -1.0f, 0.0f), XMFLOAT2(1.0f, 0.0f) });
	box.AddVertex({ XMFLOAT3(w2, -h2, d2), XMFLOAT3(0.0f, -1.0f, 0.0f), XMFLOAT2(1.0f, 1.0f) });
	box.AddVertex({ XMFLOAT3(-w2, -h2, d2), XMFLOAT3(0.0f, -1.0f, 0.0f), XMFLOAT2(0.0f, 1.0f) });

	box.AddVertex({ XMFLOAT3(-w2, -h2, d2), XMFLOAT3(-1.0f, 0.0f, 0.0f), XMFLOAT2(0.0f, 1.0f) });
	box.AddVertex({ XMFLOAT3(-w2, -h2, -d2), XMFLOAT3(-1.0f, 0.0f, 0.0f), XMFLOAT2(1.0f, 1.0f) });
	box.AddVertex({ XMFLOAT3(-w2, h2, -d2), XMFLOAT3(-1.0f, 0.0f, 0.0f), XMFLOAT2(1.0f, 0.0f) });
	box.AddVertex({ XMFLOAT3(-w2, h2, d2), XMFLOAT3(-1.0f, 0.0f, 0.0f), XMFLOAT2(0.0f, 0.0f) });

	box.AddVertex({ XMFLOAT3(w2, -h2, d2), XMFLOAT3(1.0f, 0.0f, 0.0f), XMFLOAT2(1.0f, 1.0f) });
	box.AddVertex({ XMFLOAT3(w2, -h2, -d2), XMFLOAT3(1.0f, 0.0f, 0.0f), XMFLOAT2(0.0f, 1.0f) });
	box.AddVertex({ XMFLOAT3(w2, h2, -d2), XMFLOAT3(1.0f, 0.0f, 0.0f), XMFLOAT2(0.0f, 0.0f) });
	box.AddVertex({ XMFLOAT3(w2, h2, d2), XMFLOAT3(1.0f, 0.0f, 0.0f), XMFLOAT2(1.0f, 0.0f) });

	box.AddVertex({ XMFLOAT3(-w2, -h2, -d2), XMFLOAT3(0.0f, 0.0f, -1.0f), XMFLOAT2(0.0f, 1.0f) });
	box.AddVertex({ XMFLOAT3(w2, -h2, -d2), XMFLOAT3(0.0f, 0.0f, -1.0f), XMFLOAT2(1.0f, 1.0f) });
	box.AddVertex({ XMFLOAT3(w2, h2, -d2), XMFLOAT3(0.0f, 0.0f, -1.0f), XMFLOAT2(1.0f, 0.0f) });
	box.AddVertex({ XMFLOAT3(-w2, h2, -d2), XMFLOAT3(0.0f, 0.0f, -1.0f), XMFLOAT2(0.0f, 0.0f) });

	box.AddVertex({ XMFLOAT3(-w2, -h2, d2), XMFLOAT3(0.0f, 0.0f, 1.0f), XMFLOAT2(1.0f, 1.0f) });
	box.AddVertex({ XMFLOAT3(w2, -h2, d2), XMFLOAT3(0.0f, 0.0f, 1.0f), XMFLOAT2(0.0f, 1.0f) });
	box.AddVertex({ XMFLOAT3(w2, h2, d2), XMFLOAT3(0.0f, 0.0f, 1.0f), XMFLOAT2(0.0f, 0.0f) });
	box.AddVertex({ XMFLOAT3(-w2, h2, d2), XMFLOAT3(0.0f, 0.0f, 1.0f), XMFLOAT2(1.0f, 0.0f) });

	box.AddTriangle(3, 1, 0);
	box.AddTriangle(2, 1, 3);
	box.AddTriangle(6, 4, 5);
	box.AddTriangle(7, 4, 6);
	box.AddTriangle(11, 9, 8);
	box.AddTriangle(10, 9, 11);
	box.AddTriangle(14, 12, 13);
	box.AddTriangle(15, 12, 14);
	box.AddTriangle(19, 17, 16);
	box.AddTriangle(18, 17, 19);
	box.AddTriangle(22, 20, 21);
	box.AddTriangle(23, 20, 22);

	return box;
};
Mesh MeshCreator::CreateSphere(float radius, int sliceCount, int stackCount)
{
	Mesh sphere = Mesh();
	sphere.AddVertex( 0.0f,radius,0.0f, 0.0f,1.0f,0.0f, 0.0f,0.0f);
	float phiStep = PI / stackCount;
	float thetaStep = 2.0f*PI / sliceCount;

	for (int i = 1; i <= stackCount - 1; ++i)
	{
		float phi = i*phiStep;
		for (int j = 0; j <= sliceCount; ++j)
		{
			float theta = j * thetaStep;
			XMVECTOR pv = {
				(radius*sin(phi)*cos(theta)),
				(radius*cos(phi)),
				(radius* sin(phi)*sin(theta))
			};
			
			XMVECTOR tv = { -radius*sin(phi)*sin(theta), 0, radius*sin(phi)*cos(theta) };
			tv = XMVector3Normalize(tv);

			XMVECTOR nv;
			nv = XMVector3Normalize(pv);

			XMVECTOR uvv = { theta / (PI * 2), phi / PI };

			XMFLOAT3 p, t, n;
			XMFLOAT2 uv;
			XMStoreFloat3(&p, pv);
			XMStoreFloat3(&t, tv);
			XMStoreFloat3(&n, nv);
			XMStoreFloat2(&uv, uvv);

			sphere.AddVertex({ p, n, uv });
		}
	}
	sphere.AddVertex(0.0f,-radius,0.0f, 0.0f,-1.0f,0.0f, 0.0f,1.0f);

	for (int i = 1; i <= sliceCount; i++) 
	{
		sphere.AddTriangle(0, i + 1, i);
	}

	int baseIndex = 1;
	int ringVertexCount = sliceCount + 1;

	for (int i = 0; i < stackCount - 2; ++i)
	{
		for (int j = 0; j < sliceCount; j++) {
			sphere.AddTriangle(	baseIndex + i*ringVertexCount + j,
								baseIndex + i*ringVertexCount + j + 1,
								baseIndex + (i + 1)*ringVertexCount + j);

			sphere.AddTriangle(	baseIndex + (i + 1)*ringVertexCount + j,
								baseIndex + i*ringVertexCount + j + 1,
								baseIndex + (i + 1)*ringVertexCount + j + 1);
		}
	}
	int southPoleIndex = sphere.GetVerticesCount() - 1;
	baseIndex = southPoleIndex - ringVertexCount;
	for (int i = 0; i < sliceCount; i++) {
		sphere.AddTriangle(southPoleIndex,
			baseIndex + i,
			baseIndex + i + 1);
	}
	return sphere;
}
Mesh MeshCreator::CreatePlane(float size, int sliceVertical, int sliceHorizontal)
{
	Mesh plane = Mesh();
	float a2 = size / 2.0f;

	plane.AddVertex({ XMFLOAT3(-a2, a2, 0.0f), XMFLOAT3(0.0f, 0.0f, -1.0f), XMFLOAT2(1.0f, 0.0f) });
	plane.AddVertex({ XMFLOAT3(a2, a2, 0.0f), XMFLOAT3(0.0f, 0.0f, -1.0f), XMFLOAT2(0.0f, 0.0f) });
	plane.AddVertex({ XMFLOAT3(-a2, -a2, 0.0f), XMFLOAT3(0.0f, 0.0f, -1.0f), XMFLOAT2(0.0f, 1.0f) });
	plane.AddVertex({ XMFLOAT3(a2, -a2, 0.0f), XMFLOAT3(0.0f, 0.0f, -1.0f), XMFLOAT2(1.0f, 1.0f) });

	plane.AddTriangle(0, 1, 2);
	plane.AddTriangle(2, 1, 3);

	return plane;
}